﻿using System;
using dnAnalytics.LinearAlgebra;
using dnAnalytics.LinearAlgebra.IO;
using NUnit.Framework;

namespace dnAnalytics.Tests.LinearAlgebra.IO
{
    [TestFixture]
    public class MatlabMatrixWriterTests
    {
        [Test]
        public void Constructor_ThrowsArgumentException()
        {
            Assert.Throws<ArgumentException>(() => new MatlabMatrixWriter(string.Empty));
            Assert.Throws<ArgumentException>(() => new MatlabMatrixWriter(null));
        }

        [Test]
        public void WriteMatrices_ThrowsArgumentException()
        {
            Matrix matrix = new DenseMatrix(1, 1);
            MatlabMatrixWriter writer = new MatlabMatrixWriter("somefile3");
            Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] {matrix}, new[] {string.Empty}));
            Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] {matrix}, new string[] {null}));
            Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix, matrix }, new[] { "matrix" }));
            Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix }, new[] { "some matrix" }));
            writer.Dispose();
        }

        [Test]
        public void WriteMatrices_ThrowsArgumentNullException()
        {
            MatlabMatrixWriter writer = new MatlabMatrixWriter("somefile4");
            Assert.Throws<ArgumentNullException>(() => writer.WriteMatrices(new Matrix[] {null}, new[] {"matrix"}));
            Matrix matrix = new DenseMatrix(1, 1);
            Assert.Throws<ArgumentNullException>(() => writer.WriteMatrices(new[] {matrix}, null));
            writer.Dispose();
        }

        [Test]
        public void WriteMatricesTest()
        {
            Matrix mat1 = new DenseMatrix(5, 4);
            for (int i = 0; i < mat1.Columns; i++)
            {
                mat1[i, i] = i + 1;
            }

            Matrix mat2 = new DenseMatrix(4, 5);
            for (int i = 0; i < mat2.Rows; i++)
            {
                mat2[i, i] = i + 1;
            }

            Matrix mat3 = new SparseMatrix(5, 4);
            for (int i = 0; i < mat3.Columns; i++)
            {
                mat3[i, i] = i + 1;
            }

            Matrix mat4 = new SparseMatrix(4, 5);
            for (int i = 0; i < mat4.Rows; i++)
            {
                mat4[i, i] = i + 1;
            }

            Matrix[] write = new[] {mat1, mat2, mat3, mat4};

            string[] names = new[] {"mat1", "dense_matrix_2", "s1", "sparse2"};
            MatlabMatrixWriter writer = new MatlabMatrixWriter("test.mat");
            writer.WriteMatrices(write, names);
            writer.Dispose();

            MatlabMatrixReader reader = new MatlabMatrixReader("test.mat");
            Matrix[] read = reader.ReadMatrices(names);

            Assert.AreEqual(write.Length, read.Length);
            for (int matrix = 0; matrix < write.Length; matrix++)
            {
                Assert.AreEqual(write[matrix].Rows, read[matrix].Rows);
                Assert.AreEqual(write[matrix].Columns, read[matrix].Columns);
                Assert.That(write[matrix], Is.EqualTo(read[matrix]));
            }
        }

        [Test]
        public void WriteMatrix_ThrowsArgumentException()
        {
            Matrix matrix = new DenseMatrix(1, 1);
            MatlabMatrixWriter writer = new MatlabMatrixWriter("somefile1");
            Assert.Throws<ArgumentException>(() => writer.WriteMatrix(matrix, string.Empty));
            Assert.Throws<ArgumentException>(() => writer.WriteMatrix(matrix, null));
            writer.Dispose();
        }

        [Test]
        public void WriteMatrix_ThrowsArgumentNullException()
        {
            MatlabMatrixWriter writer = new MatlabMatrixWriter("somefile2");
            Assert.Throws<ArgumentNullException>(() => writer.WriteMatrix(null, "matrix"));
            writer.Dispose();
        }
    }
}
